/*
 * copy from http://www.cnblogs.com/mcodec/articles/1780598.html
 *
 */
package wangjg.android.media.h264;

import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.util.Log;
import android.view.View;

public class VView extends View implements Runnable {
	private int width = 240; // 此处设定不同的分辨率
	private int height = 320;

	private byte[] mPixel = new byte[width * height * 2];
	private ByteBuffer buffer = ByteBuffer.wrap(mPixel);
	private Bitmap videoBit = Bitmap.createBitmap(width, height, Config.RGB_565);

	private int mTrans = 0x0F0F0F0F;
	private String currentFilePath;

	private Decoder decoder = new Decoder();
	private int InitDecoder(int width, int height){return decoder.InitDecoder(width, height);}
	private int UninitDecoder(){return decoder.UninitDecoder();}
	private int DecoderNal(byte[] in, int insize, byte[] out){return decoder.DecoderNal(in, insize, out);}

	public VView(Context context) {
		super(context);
		setFocusable(true);
	}

	public void PlayVideo(String file) {
		currentFilePath = file;
		new Thread(this).start();
	}

	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);

		// Bitmap tmpBit = Bitmap.createBitmap(mPixel, 320, 480,
		// Bitmap.Config.RGB_565);//.ARGB_8888);

		videoBit.copyPixelsFromBuffer(buffer);// makeBuffer(data565, N));

		canvas.drawBitmap(videoBit, 0, 0, null);
	}

	public void run() {
		boolean bFirst = true;
		boolean bFindPPS = true;
	
		int bytesRead = 0;
		int NalBufUsed = 0;
	
		byte[] NalBuf = new byte[40980]; // 40k
		byte[] SockBuf = new byte[2048];
	
		FileInputStream fileIS = null;
		try {
			fileIS = new FileInputStream(currentFilePath);
		} catch (IOException e) {
			Log.e(this.getClass().getName(), e.getMessage());
			e.printStackTrace();
			return;
		}
	
		InitDecoder(width, height);
	
		while (!Thread.currentThread().isInterrupted()) {
			try {
				bytesRead = fileIS.read(SockBuf, 0, 2048);
			} catch (IOException e) {
				e.printStackTrace();
			}
	
			if (bytesRead <= 0)
				break;
	
			int SockBufUsed = 0;
	
			while (bytesRead - SockBufUsed > 0) {
				int nalLen = MergeBuffer(NalBuf, NalBufUsed, SockBuf, SockBufUsed, bytesRead - SockBufUsed);
	
				NalBufUsed += nalLen;
				SockBufUsed += nalLen;
	
				if (mTrans == 1) {
					mTrans = 0xFFFFFFFF;
	
					if (bFirst == true){ // the first start flag
						bFirst = false;
					} else {// a complete NAL data, include 0x00000001 trail.
						if (bFindPPS == true){ // true
							if ((NalBuf[4] & 0x1F) == 7) {
								bFindPPS = false;
							} else {
								NalBuf[0] = 0;
								NalBuf[1] = 0;
								NalBuf[2] = 0;
								NalBuf[3] = 1;
	
								NalBufUsed = 4;
	
								break;
							}
						}
						// decode nal
						int iTemp = DecoderNal(NalBuf, NalBufUsed - 4, mPixel);
	
						if (iTemp > 0)
							postInvalidate(); // 使用postInvalidate可以直接在线程中更新界面 //
												// postInvalidate();
					}
	
					NalBuf[0] = 0;
					NalBuf[1] = 0;
					NalBuf[2] = 0;
					NalBuf[3] = 1;
	
					NalBufUsed = 4;
				}
			}
		}
		try {
			if (fileIS != null)
				fileIS.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		UninitDecoder();
	}
	
	private int MergeBuffer(byte[] NalBuf, int NalBufUsed, byte[] SockBuf, int SockBufUsed, int SockRemain) {
		int i = 0;

		for (i = 0; i < SockRemain; i++) {
			byte b = SockBuf[i + SockBufUsed];
			NalBuf[i + NalBufUsed] = b;

			mTrans <<= 8;
			mTrans |= b;

			if (mTrans == 1){ // 找到一个开始字
				i++;
				break;
			}
		}

		return i;
	}
}
